

package com.maoshi.shop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maoshi.shop.bean.app.dto.ProductDto;
import com.maoshi.shop.bean.app.dto.TagProductDto;
import com.maoshi.shop.bean.app.param.SearchParam;
import com.maoshi.shop.bean.dto.ProdAndSkuListsDto;
import com.maoshi.shop.bean.dto.SearchProdDto;
import com.maoshi.shop.bean.enums.*;
import com.maoshi.shop.bean.model.*;
import com.maoshi.shop.bean.param.GrowthParamConfig;
import com.maoshi.shop.bean.enums.ProdType;
import com.maoshi.shop.bean.model.OfflineHandleEvent;
import com.maoshi.shop.bean.model.Product;
import com.maoshi.shop.bean.model.Sku;
import com.maoshi.shop.bean.param.OfflineHandleEventAuditParam;
import com.maoshi.shop.bean.param.ProductParam;
import com.maoshi.shop.common.config.Constant;
import com.maoshi.shop.common.exception.MaoshiShopBindException;
import com.maoshi.shop.common.util.Arith;
import com.maoshi.shop.common.util.PageParam;
import com.maoshi.shop.dao.*;
import com.maoshi.shop.service.OfflineHandleEventService;
import com.maoshi.shop.service.ProductService;
import com.maoshi.shop.service.SysConfigService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    private final ProductMapper productMapper;
    private final SkuMapper skuMapper;
    private final OfflineHandleEventService offlineHandleEventService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveProduct(Product product) {
        productMapper.insert(product);
        if (CollectionUtil.isNotEmpty(product.getSkuList())) {
            skuMapper.insertBatch(product.getProdId(), product.getSkuList());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#product.prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#product.prodId")
    })
    public void updateProduct(Product product, Product dbProduct) {
        // 使用保存或更新，可以仅更新非null的数据
        saveOrUpdate(product);
        List<Long> dbSkuIds = dbProduct.getSkuList().stream().map(Sku::getSkuId).collect(Collectors.toList());
        // 2019/04/c0244be79909484fb67bc6d5f70cae18.jpg
//        if (!Objects.equals(dbProduct.getPic(), product.getPic()) && StrUtil.isNotBlank(dbProduct.getPic())) {
//            // 删除数据库中的商品图片
//            attachFileService.deleteFile(dbProduct.getPic());
//        }
        // 将所有该商品的sku标记为已删除状态
        skuMapper.deleteByProdId(product.getProdId());

        // 接口传入sku列表
        List<Sku> skuList = product.getSkuList();

        if (CollectionUtil.isEmpty(skuList)) {
            return;
        }

        List<Sku> insertSkuList = new ArrayList<>();
        for (Sku sku : skuList) {
            sku.setIsDelete(0);
            // 如果数据库中原有sku就更新，否者就插入
            if (dbSkuIds.contains(sku.getSkuId())) {
                skuMapper.updateById(sku);
            } else {
//                if (dbProduct.getGroupActivityId() != null && dbProduct.getGroupActivityId() != 0) {
                if (dbProduct.getProdType() != null && dbProduct.getProdType().equals(ProdType.PROD_TYPE_GROUP.value())) {
                    throw new MaoshiShopBindException("商品正在参与拼团活动，无法修改规格");
                }
                insertSkuList.add(sku);
            }
        }
        // 批量插入sku
        if (CollectionUtil.isNotEmpty(insertSkuList)) {
            skuMapper.insertBatch(product.getProdId(), insertSkuList);
        }
    }


    /**
     * 这里的缓存 1800秒消失，详情RedisCacheConfig这里的配置
     * 当秒杀的时候，并不更新这里的缓存，所以库存会滞后，但是半个小时后缓存消失，又会重新获取
     *
     * @param prodId
     * @return
     */
    @Override
    @Cacheable(cacheNames = "product", key = "#prodId")
    public Product getProductByProdId(Long prodId) {
        return productMapper.selectById(prodId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#prodId")
    })
    public void removeProductByProdId(Long prodId) {
//        Product dbProduct = getProductByProdId(prodId);

        // 将商品的状态变成-1（逻辑删除）
        Product product = new Product();
        product.setProdId(prodId);
        product.setStatus(-1);
        saveOrUpdate(product);

        skuMapper.deleteByProdId(prodId);
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#prodId")
    })
    public void removeProductCacheByProdId(Long prodId) {


    }

    @Override
    public IPage<ProductDto> pageByPutawayTime(IPage<ProductDto> page) {
        return productMapper.pageByPutawayTime(page);
    }

    @Override
    public IPage<ProductDto> pageByScore(IPage<ProductDto> page) {


        return productMapper.pageByScore(page);
    }



    @Override
    public IPage<ProductDto> pageByTagId(Page<ProductDto> page, Long tagId) {
        return productMapper.pageByTagId(page, tagId);
    }


    @Override
    public IPage<ProductDto> moreBuyProdList(Page<ProductDto> page) {
        return productMapper.moreBuyProdList(page);
    }

    @Override
    public IPage<SearchProdDto> getSearchProdDtoPageByProdName(Page page, SearchParam searchParam) {
        IPage<SearchProdDto> searchProdDtoPage = productMapper.getSearchProdDtoPageByProdName(page, searchParam);
        for (SearchProdDto searchProdDto : searchProdDtoPage.getRecords()) {
            //计算出好评率
            if (searchProdDto.getPraiseNumber() == 0 || searchProdDto.getProdCommNumber() == 0) {
                searchProdDto.setPositiveRating(0.0);
            } else {
                searchProdDto.setPositiveRating(Arith.div(Arith.mul(searchProdDto.getPraiseNumber(), 100), searchProdDto.getProdCommNumber()));
            }
        }
        return searchProdDtoPage;
    }

    @Override
    public List<TagProductDto> tagProdList() {
        return productMapper.tagProdList();
    }

    @Override
    public IPage<ProductDto> pageByDiscountId(Page<ProductDto> page, Long discountId) {
        return productMapper.pageByDiscountId(page, discountId);
    }

    @Override
    public IPage<ProductDto> collectionProds(PageParam page, String userId) {
        return productMapper.collectionProds(page, userId);
    }

    @Override
    public List<ProdAndSkuListsDto> getProdAndSkuLists(List<Long> prodIds) {
        return productMapper.getProdAndSkuLists(prodIds);
    }

    @Override
    public void updateProductToGroup(Long groupActivityId, List<Long> prodIds) {
        productMapper.updateProductToGroup(groupActivityId, prodIds);
    }

    @Override
    public void updateProductToUnGroup(Long prodId) {
        productMapper.updateProductToUnGroup(prodId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long prodId, String reapplyReason) {
        // 更新商品为待审核状态
        productMapper.updateToApply(prodId);
        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void prodAudit(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过,更新商品状态
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            productMapper.updateToShopOffline(offlineHandleEventAuditParam.getHandleId());
        } else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            productMapper.updateToOffline(offlineHandleEventAuditParam.getHandleId());
        }
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offline(Long prodId, String offlineReason, Long sysUserId) {
        Product product = getProductByProdId(prodId);

        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleType(OfflineHandleEventType.PROD.getValue());
        offlineHandleEvent.setHandleId(product.getProdId());
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setShopId(product.getShopId());
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 更新活动状态为下线
        productMapper.updateToOffline(prodId);
    }

    @Override
    public IPage<Product> getPageAngShopName(PageParam<Product> page, ProductParam product) {
        return productMapper.getPageAndShopName(page,product);
    }



}
